#include "util/util.h"
#include <assert.h>
using namespace util;
static const float WHITE[] = { 1.0f, 1.0f, 1.0f, 1.0f };
static const float RED[] = { 1.0f, 0.0f, 0.0f, 1.0f };
static const float GREEN[] = { 0.0f, 1.0f, 0.0f, 1.0f };
static const float BLUE[] = { 0.0f, 0.0f, 1.0f, 1.0f };
static const float YELLOW[] = { 1.0f, 1.0f, 0.0f, 1.0f };
const int SCR_W = 640;
const int SCR_H = 480;
CGeometry obj;
float ang1 = 0, ang2 = 0;
CCamera cam;

void init()
{
	glViewport(0, 0, SCR_W, SCR_H);
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glClearDepth(1.0);
	glEnable(GL_DEPTH_TEST);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_NORMALIZE);
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);
	
	obj.create_sphere(64);
	
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glLightfv(GL_LIGHT0, GL_AMBIENT, WHITE);
	
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	cam.perspective(45.0f, (float)SCR_W/SCR_H, 0.1f, 1000.f);
}
void frame()
{

}
void render()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	
	glVertexPointer(3, GL_FLOAT, 0, obj.get_vertex());
	glNormalPointer(GL_FLOAT, 0, obj.get_normal());
	
	// center large sphere
	glTranslatef(0.0f, 0.0f, -5.0f);
	static const float MAT_COL1[] = { 0.2f, 0.1f, 0.0f, 1.0f };
	static const float MAT_SCL1[] = { 0.3f, 0.15f, 0.0f, 1.0f };
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, MAT_COL1);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, MAT_SCL1);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 128.0f);
	glDrawElements(GL_TRIANGLES, obj.get_index_num(), GL_UNSIGNED_SHORT, obj.get_index_data());
	
	// enable blend and disable depth buffer writeable
	glEnable(GL_BLEND);
	glDepthMask(GL_FALSE);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE);
	
	// rotate green blend sphere
	glPushMatrix();
		glRotatef(ang1, 0.0f, 1.0f, 0.0f);
		ang1 += 1.5f;
		glTranslatef(0.0f, 0.4f, -1.8f);
		glScalef(0.3f, 0.3f, 0.3f);
		static const float MAT_COL2[] = { 0.0f, 0.2f, 0.0f, 0.5f };
		static const float MAT_SCL2[] = { 0.0f, 0.3f, 0.0f, 0.5f };
		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, MAT_COL2);
		glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, MAT_SCL2);
		glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 128.0f);
		glDrawElements(GL_TRIANGLES, obj.get_index_num(), GL_UNSIGNED_SHORT, obj.get_index_data());
	glPopMatrix();
	
	// rotate red blend sphere
	glPushMatrix();
		glRotatef(ang2, 0.0f, 1.0f, 0.0f);
		ang2 -= 1.5f;
		glTranslatef(0.0f, -0.4f, 1.8f);
		glScalef(0.3f, 0.3f, 0.3f);
		static const float MAT_COL3[] = { 0.2f, 0.0f, 0.0f, 0.5f };
		static const float MAT_SCL3[] = { 0.3f, 0.0f, 0.0f, 0.5f };
		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, MAT_COL3);
		glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, MAT_SCL3);
		glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 128.0f);
		glDrawElements(GL_TRIANGLES, obj.get_index_num(), GL_UNSIGNED_SHORT, obj.get_index_data());
	glPopMatrix();
	
	// reset state
	glDepthMask(GL_TRUE);
	glDisable(GL_BLEND);
}

int main()
{
	g_p_system = new CSystem(SCR_W, SCR_H, "Blend by qq.d.y");
	g_p_system->set_callback(CSystem::INIT, init);
	g_p_system->set_callback(CSystem::RENDER, render);
	g_p_system->set_callback(CSystem::FRAME, frame);
	g_p_system->run();
	return 0;
}